# uncompyle6 version 2.15.1
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.10 (default, Jul  1 2017, 13:36:56) 
# [GCC 4.4.6 20110731 (Red Hat 4.4.6-4)]
# Embedded file name: ./paas/common/pxfilter.py
# Compiled at: 2017-11-16 15:44:28
"""
Tencent is pleased to support the open source community by making \xe8\x93\x9d\xe9\xb2\xb8\xe6\x99\xba\xe4\xba\x91(BlueKing) available.
Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.

Python \xe5\xaf\x8c\xe6\x96\x87\xe6\x9c\xacXSS\xe8\xbf\x87\xe6\xbb\xa4\xe7\xb1\xbb
@package XssHtml
@version 0.1
@link http://phith0n.github.io/python-xss-filter
@since 20150407
@copyright (c) Phithon All Rights Reserved
Based on native Python module HTMLParser purifier of HTML, To Clear all javascript in html
You can use it in all python web framework
Written by Phithon <root@leavesongs.com> in 2015 and placed in the public domain.
phithon <root@leavesongs.com> \xe7\xbc\x96\xe5\x86\x99\xe4\xba\x8e20150407
From: XDSEC <www.xdsec.org> & \xe7\xa6\xbb\xe5\x88\xab\xe6\xad\x8c <www.leavesongs.com>
GitHub Pages: https://github.com/phith0n/python-xss-filter
Usage:
    parser = XssHtml()
    parser.feed('<html code>')
    parser.close()
    html = parser.getHtml()
    print html
Requirements
Python 2.6+ or 3.2+
Cannot defense xss in browser which is belowed IE7
\xe6\xb5\x8f\xe8\xa7\x88\xe5\x99\xa8\xe7\x89\x88\xe6\x9c\xac\xef\xbc\x9aIE7+ \xe6\x88\x96\xe5\x85\xb6\xe4\xbb\x96\xe6\xb5\x8f\xe8\xa7\x88\xe5\x99\xa8\xef\xbc\x8c\xe6\x97\xa0\xe6\xb3\x95\xe9\x98\xb2\xe5\xbe\xa1IE6\xe5\x8f\x8a\xe4\xbb\xa5\xe4\xb8\x8b\xe7\x89\x88\xe6\x9c\xac\xe6\xb5\x8f\xe8\xa7\x88\xe5\x99\xa8\xe4\xb8\xad\xe7\x9a\x84XSS
"""
import re
from HTMLParser import HTMLParser

class XssHtml(HTMLParser):
    allow_tags = [
     'a', 'img', 'br', 'strong', 'b', 'code', 'pre',
     'p', 'div', 'em', 'span', 'h1', 'h2', 'h3', 'h4',
     'h5', 'h6', 'blockquote', 'ul', 'ol', 'tr', 'th', 'td',
     'hr', 'li', 'u', 'embed', 's', 'table', 'thead', 'tbody',
     'caption', 'small', 'q', 'sup', 'sub']
    common_attrs = ['id', 'style', 'class', 'name']
    nonend_tags = ['img', 'hr', 'br', 'embed']
    tags_own_attrs = {'img': [
             'src', 'width', 'height', 'alt', 'align'],
       'a': [
           'href', 'target', 'rel', 'title'],
       'embed': [
               'src', 'width', 'height', 'type', 'allowfullscreen', 'loop', 'play', 'wmode', 'menu'],
       'table': [
               'border', 'cellpadding', 'cellspacing']
       }

    def __init__(self, allows=[]):
        HTMLParser.__init__(self)
        self.allow_tags = allows if allows else self.allow_tags
        self.result = []
        self.start = []
        self.data = []

    def getHtml(self):
        """
        Get the safe html code
        """
        for i in range(0, len(self.result)):
            tmp = self.result[i].rstrip('\n')
            tmp = tmp.lstrip('\n')
            if tmp:
                self.data.append(tmp)

        return ('').join(self.data)

    def handle_startendtag(self, tag, attrs):
        self.handle_starttag(tag, attrs)

    def handle_starttag(self, tag, attrs):
        if tag not in self.allow_tags:
            return
        if tag in self.nonend_tags:
            end_diagonal = ' /' if 1 else ''
            end_diagonal or self.start.append(tag)
        attdict = {}
        for attr in attrs:
            attdict[attr[0]] = attr[1]

        attdict = self.__wash_attr(attdict, tag)
        if hasattr(self, 'node_%s' % tag):
            attdict = getattr(self, 'node_%s' % tag)(attdict)
        else:
            attdict = self.node_default(attdict)
        attrs = []
        for key, value in attdict.items():
            attrs.append('%s="%s"' % (key, self.__htmlspecialchars(value)))

        attrs = ' ' + (' ').join(attrs) if attrs else ''
        self.result.append('<' + tag + attrs + end_diagonal + '>')

    def handle_endtag(self, tag):
        if self.start and tag == self.start[len(self.start) - 1]:
            self.result.append('</' + tag + '>')
            self.start.pop()

    def handle_data(self, data):
        self.result.append(self.__htmlspecialchars(data))

    def handle_entityref(self, name):
        if name.isalpha():
            self.result.append('&%s;' % name)

    def handle_charref(self, name):
        if name.isdigit():
            self.result.append('&#%s;' % name)

    def node_default(self, attrs):
        attrs = self.__common_attr(attrs)
        return attrs

    def node_a(self, attrs):
        attrs = self.__common_attr(attrs)
        attrs = self.__get_link(attrs, 'href')
        attrs = self.__set_attr_default(attrs, 'target', '_blank')
        attrs = self.__limit_attr(attrs, {'target': [
                    '_blank', '_self']
           })
        return attrs

    def node_embed(self, attrs):
        attrs = self.__common_attr(attrs)
        attrs = self.__get_link(attrs, 'src')
        attrs = self.__limit_attr(attrs, {'type': [
                  'application/x-shockwave-flash'],
           'wmode': [
                   'transparent', 'window', 'opaque'],
           'play': [
                  'true', 'false'],
           'loop': [
                  'true', 'false'],
           'menu': [
                  'true', 'false'],
           'allowfullscreen': [
                             'true', 'false']
           })
        attrs['allowscriptaccess'] = 'never'
        attrs['allownetworking'] = 'none'
        return attrs

    def __true_url(self, url):
        prog = re.compile('^(http|https|ftp)://.+', re.I | re.S)
        if prog.match(url):
            return url
        return 'http://%s' % url

    def __true_style(self, style):
        if style:
            style = re.sub('(\\\\|&#|/\\*|\\*/)', '_', style)
            style = re.sub('e.*x.*p.*r.*e.*s.*s.*i.*o.*n', '_', style)
        return style

    def __get_style(self, attrs):
        if 'style' in attrs:
            attrs['style'] = self.__true_style(attrs.get('style'))
        return attrs

    def __get_link(self, attrs, name):
        if name in attrs:
            attrs[name] = self.__true_url(attrs[name])
        return attrs

    def __wash_attr(self, attrs, tag):
        if tag in self.tags_own_attrs:
            other = self.tags_own_attrs.get(tag)
        else:
            other = []
        if attrs:
            for key, value in attrs.items():
                if key not in self.common_attrs + other:
                    del attrs[key]

        return attrs

    def __common_attr(self, attrs):
        attrs = self.__get_style(attrs)
        return attrs

    def __set_attr_default(self, attrs, name, default=''):
        if name not in attrs:
            attrs[name] = default
        return attrs

    def __limit_attr(self, attrs, limit={}):
        for key, value in limit.items():
            if key in attrs and attrs[key] not in value:
                del attrs[key]

        return attrs

    def __htmlspecialchars(self, html):
        return html.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#039;')


if '__main__' == __name__:
    parser = XssHtml()
    parser.feed('<p><img src=1 onerror=alert(/xss/)></p><div class="left">\n        <a href=\'javascript:prompt(1)\'><br />hehe</a></div>\n        <p id="test" onmouseover="alert(1)">&gt;M<svg>\n        <a href="https://www.baidu.com" target="self">MM</a></p>\n        <embed src=\'javascript:alert(/hehe/)\' allowscriptaccess=always />')
    parser.close()
    print parser.getHtml()